package com.boby.homecamera.webserver.controller

import android.text.TextUtils
import com.boby.homecamera.config.AppConfig
import com.boby.homecamera.constant.Constant
import com.boby.homecamera.db.DBManager
import com.boby.homecamera.db.VideoEventTable
import com.boby.homecamera.db.VideoTable.Video
import com.boby.homecamera.util.FileUtil
import com.boby.homecamera.util.FileUtils
import com.boby.homecamera.webserver.body.RandomFileBody
import com.boby.homecamera.webserver.body.RangeFileBody
import com.boby.homecamera.webserver.model.UserInfo
import com.boby.lib_common.util.BLog
import com.pedro.encoder.input.decoder.VideoInfo
import com.yanzhenjie.andserver.annotation.Addition
import com.yanzhenjie.andserver.annotation.GetMapping
import com.yanzhenjie.andserver.annotation.RequestMapping
import com.yanzhenjie.andserver.annotation.RestController
import com.yanzhenjie.andserver.error.HttpException
import com.yanzhenjie.andserver.framework.body.FileBody
import com.yanzhenjie.andserver.http.HttpRequest
import com.yanzhenjie.andserver.http.HttpResponse
import com.yanzhenjie.andserver.http.StatusCode
import com.yanzhenjie.andserver.util.MediaType
import java.io.File
import java.io.RandomAccessFile
import com.yanzhenjie.andserver.http.ResponseBody


@RestController
@RequestMapping(path = ["/video"])
class VideoController {
    private val TAG = "VideoController"

    @Addition(stringType = ["login"], booleanType = [true])
    @GetMapping("/last.mp4", produces = ["video/mp4"] )
    fun last(): FileBody? {
        var lastVide = DBManager.instance.tb_video.queryLast()
        BLog.d(TAG,"last ${lastVide?.path}")
        if(lastVide == null){
            return null
        }
        val file = File(lastVide.path)
        if (!file.exists()) {
            throw HttpException(Constant.ErrorCode.ERROR_CODE_FILE_NOT_EXIST, "视频不存在")
        }
        return FileBody(file)
    }

    @Addition(stringType = ["login"], booleanType = [true])
    @GetMapping("/lastpic", produces = [MediaType.IMAGE_JPEG_VALUE] )
    fun lastPic(): FileBody? {
        BLog.d(TAG,"lastPic ")
        var picDirFile = File(Constant.RECORD_FILE_PIC_DIR +"temp")
        if(!picDirFile.exists()){
            picDirFile.mkdirs()
        }
        var listFiles = picDirFile.listFiles()
        var lastPicFile : File? = null
        if (!listFiles.isNullOrEmpty()) {
            val sorted = listFiles.sortedByDescending { it.lastModified() }
            lastPicFile = sorted.first()
            if(sorted.size > 30){
                //最近的文件排前面
                sorted.last().delete()
            }
        }
        var lastVide = DBManager.instance.tb_video.queryLast()
        BLog.d(TAG,"last ${lastVide?.path}")
        if(lastVide == null){
            if(lastPicFile != null){
                return FileBody(lastPicFile)
            }
            throw HttpException(Constant.ErrorCode.ERROR_CODE_FILE_NOT_EXIST, "暂无缓存封面")
        }

        val videoFile = File(lastVide.path)

        if (!videoFile.exists()) {
            if(lastPicFile != null){
                return FileBody(lastPicFile)
            }
            throw HttpException(Constant.ErrorCode.ERROR_CODE_FILE_NOT_EXIST, "暂无缓存封面")
        }else{
            val picThumbFile = File(videoFile.absolutePath.replace(".mp4",".jpeg",true))
            if(picThumbFile.exists()){
                return FileBody(picThumbFile)
            }
            var picName = lastPicFile?.name?.replace(".jpeg","",true)
            var mp4Name = videoFile.name.replace(".mp4","",true)
            if( picName != null && picName == mp4Name){
               return FileBody(lastPicFile)
            }

            val localVideoInfo = FileUtils.getLocalVideoBitmap(videoFile.path)
            val picFile = "${picDirFile.absolutePath}/${mp4Name}.jpeg"
            FileUtil.saveBitmapToDir(localVideoInfo?.first,null,picFile)
            return FileBody(File(picFile))
        }

    }

    @Addition(stringType = ["login"], booleanType = [true])
    @GetMapping("/getpic", produces = [MediaType.IMAGE_JPEG_VALUE] )
    fun getPic(request: HttpRequest): FileBody? {
        var picPath = request.getParameter("path")
        if(picPath.isNullOrEmpty()){
            throw HttpException(Constant.ErrorCode.ERROR_CODE_FILE_NOT_EXIST, "路径不能为空")
        }
        if(picPath.endsWith(".mp4")){
            picPath = picPath.replace(".mp4",".jpeg",true)
        }
        val picFile = File(picPath)
        if(!picFile.exists()){
            throw HttpException(Constant.ErrorCode.ERROR_CODE_FILE_NOT_EXIST, "文件不存在")
        }
       return FileBody(picFile)
    }

    @Addition(stringType = ["login"], booleanType = [true])
    @GetMapping("/lastvideo")
    fun lastVideo(request: HttpRequest, response: HttpResponse):ResponseBody {
        val video = DBManager.instance.tb_video.queryLast()
            ?: throw HttpException(404, "视频记录不存在")
        BLog.d(TAG,"")
        val file = File(video.path)
        if (!file.exists()) throw HttpException(404, "文件不存在")

        var range = request.getHeader("Range")
        if (!TextUtils.isEmpty(range)) {
            //开始下载位置
            var startByte: Long = 0
            //结束下载位置
            var endByte = file.length() - 1
            //有range的话
            if (range != null && range.contains("bytes=") && range.contains("-")) {
                range = range.substring(range.lastIndexOf("=") + 1).trim { it <= ' ' }
                val ranges: Array<String?>? =
                    range.split("-".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                try {
                    //判断range的类型
                    if (ranges!!.size == 1) {
                        //类型一：bytes=-2343
                        if (range.startsWith("-")) {
                            endByte = ranges[0]!!.toLong()
                        } else if (range.endsWith("-")) {
                            startByte = ranges[0]!!.toLong()
                        }
                    } else if (ranges.size == 2) {
                        startByte = ranges[0]!!.toLong()
                        endByte = ranges[1]!!.toLong()
                    }
                } catch (e: NumberFormatException) {
                    startByte = 0
                    endByte = file.length() - 1
                }
            }

            //要下载的长度（为啥要加一问小学数学老师去）
            val contentLength = endByte - startByte + 1
            //文件名
            val fileName = file.getName()
            //文件类型
            val contentType = MediaType.getFileMediaType(file.getName())


            //各种响应头设置
            //参考资料：https://www.ibm.com/developerworks/cn/java/joy-down/index.html
            //坑爹地方一：看代码
            response.setHeader("Accept-Ranges", "bytes")
            //坑爹地方二：http状态码要为206
            response.setStatus(StatusCode.SC_PARTIAL_CONTENT)

            //            response.setHeader("Content-Length", String.valueOf(contentLength));
            //坑爹地方三：Content-Range，格式为
            // [要下载的开始位置]-[结束位置]/[文件总大小]
            response.setHeader(
                "Content-Range",
                "bytes " + startByte + "-" + endByte + "/" + file.length()
            )


            val raf = RandomAccessFile(file, "r")

//            response.setBody(RandomFileBody(startByte, endByte, raf, contentLength, contentType))
            return  RandomFileBody(startByte, endByte, raf, contentLength, contentType)
        } else {
            response.status = StatusCode.SC_OK
//            response.setBody(FileBody(file))
            return FileBody(file)
        }
    }

    @Addition(stringType = ["login"], booleanType = [true])
    @GetMapping("/getvideo")
    fun getVideo(request: HttpRequest, response: HttpResponse):ResponseBody {
        var videoPath = request.getParameter("path")
        if(videoPath.isNullOrEmpty()){
            throw HttpException(Constant.ErrorCode.ERROR_CODE_FILE_NOT_EXIST, "路径不能为空")
        }

        val file = File(videoPath)
        if (!file.exists()) throw HttpException(404, "文件不存在")

        var range = request.getHeader("Range")
        if (!TextUtils.isEmpty(range)) {
            //开始下载位置
            var startByte: Long = 0
            //结束下载位置
            var endByte = file.length() - 1
            //有range的话
            if (range != null && range.contains("bytes=") && range.contains("-")) {
                range = range.substring(range.lastIndexOf("=") + 1).trim { it <= ' ' }
                val ranges: Array<String?>? =
                    range.split("-".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                try {
                    //判断range的类型
                    if (ranges!!.size == 1) {
                        //类型一：bytes=-2343
                        if (range.startsWith("-")) {
                            endByte = ranges[0]!!.toLong()
                        } else if (range.endsWith("-")) {
                            startByte = ranges[0]!!.toLong()
                        }
                    } else if (ranges.size == 2) {
                        startByte = ranges[0]!!.toLong()
                        endByte = ranges[1]!!.toLong()
                    }
                } catch (e: NumberFormatException) {
                    startByte = 0
                    endByte = file.length() - 1
                }
            }

            //要下载的长度（为啥要加一问小学数学老师去）
            val contentLength = endByte - startByte + 1
            //文件名
            val fileName = file.getName()
            //文件类型
            val contentType = MediaType.getFileMediaType(file.getName())


            //各种响应头设置
            //参考资料：https://www.ibm.com/developerworks/cn/java/joy-down/index.html
            //坑爹地方一：看代码
            response.setHeader("Accept-Ranges", "bytes")
            //坑爹地方二：http状态码要为206
            response.setStatus(StatusCode.SC_PARTIAL_CONTENT)

            //            response.setHeader("Content-Length", String.valueOf(contentLength));
            //坑爹地方三：Content-Range，格式为
            // [要下载的开始位置]-[结束位置]/[文件总大小]
            response.setHeader(
                "Content-Range",
                "bytes " + startByte + "-" + endByte + "/" + file.length()
            )


            val raf = RandomAccessFile(file, "r")

//            response.setBody(RandomFileBody(startByte, endByte, raf, contentLength, contentType))
            return  RandomFileBody(startByte, endByte, raf, contentLength, contentType)
        } else {
            response.status = StatusCode.SC_OK
//            response.setBody(FileBody(file))
            return FileBody(file)
        }
    }


    @Addition(stringType = ["login"], booleanType = [true])
    @GetMapping(path = ["/videolist"], produces = [MediaType.APPLICATION_JSON_UTF8_VALUE] )
    fun getVideoList(request: HttpRequest): List<Video> {
        val startTime = request.getParameter("startTime")?.toLong()
        val endTime = request.getParameter("endTime")?.toLong()
//        BLog.d(TAG,"getVideoList startTime:$startTime ,endTime:$endTime")
        val queryVideos = DBManager.instance.tb_video.queryVideos(startTime, endTime)
//        BLog.d(TAG,"getVideoList queryVideos size:${queryVideos.size}")
        val sortList = queryVideos.sortedByDescending { it.startTime }
        val videoList = mutableListOf<Video>()
        var notExistCount = 0
        for (video in sortList) {
            val videoFile  = File(video.path)
            try {
//                BLog.d(TAG,"getVideoList isFile:${videoFile.path}")
                if(videoFile.exists()){
                    videoList.add(0,video)
                }else{
                    notExistCount ++
                    if(notExistCount > 10){
                        break
                    }
                }
            }catch (e: Exception){
                e.printStackTrace()
            }

        }
//        BLog.d(TAG,"getVideoList size:${videoList.size}")
      return videoList
    }


    @Addition(stringType = ["login"], booleanType = [true])
    @GetMapping(path = ["/video_event_list"], produces = [MediaType.APPLICATION_JSON_UTF8_VALUE] )
    fun getVideoEvent(request: HttpRequest): List<VideoEventTable.VideoEvent> {
        val startTime = request.getParameter("startTime")?.toLong()
        val endTime = request.getParameter("endTime")?.toLong()
        val videoEventTypes = request.getParameter("videoEventTypes")
        val isASC = request.getParameter("isASC")?.toBoolean()?:true
        BLog.d(TAG,"startTime:$startTime ,endTime:$endTime")
        val queryVideoEvents = DBManager.instance.tb_videoEvent.queryVideoEvents(startTime, endTime,videoEventTypes,isASC)
        BLog.d(TAG,"type:$videoEventTypes ,queryVideoEvents:$queryVideoEvents")
        return queryVideoEvents
    }

    @Addition(stringType = ["login"], booleanType = [true])
    @GetMapping(path = ["/video_Start_file_date"], produces = [MediaType.APPLICATION_JSON_UTF8_VALUE] )
    fun getVideoStartFileDate(request: HttpRequest): Long {
        val dir = File(Constant.RECORD_FILE_DIR)
        // 按最后修改时间排序
        val fileList = dir.listFiles()
//        val sortedByTime = fileList?.sortedByDescending { it.lastModified() }
        fileList?.sort()
        try {
            fileList?.forEach {
                val fileName = it.name
                if(fileName.endsWith(".mp4")){
                    val timeString = fileName.replace(".mp4", "")
                    return timeString.toLong()
                }
            }
        }catch (e: Exception){
            e.printStackTrace()
        }

        return -1
    }
}